#include<stdlib.h>
#include<stdio.h>
#include"box.h"
#include"algfloat.h"

bool Box::Hit_aux(Ray * ray, float* p, float* d)
{
  float tmin, tmax, txmax, txmin, tymin, tymax, tzmin, tzmax;
  float shadow = ray->shadow_mode;
  if(p==NULL){
    p = ray->GetP(shadow?SHADOW_RAY:VIEW_RAY);
    d = ray->GetD(shadow?SHADOW_RAY:VIEW_RAY);
  }
  float divx = 1/d[0];
  if (divx>=0.0) {
    tmin = (min[0] - p[0])*divx;
    tmax = (max[0] - p[0])*divx;
  }
  else{
    tmin = (max[0] - p[0])*divx;
    tmax = (min[0] - p[0])*divx;
  }
  txmax=tmax;
  txmin=tmin;
  float divy = 1/d[1];
  if (divy>=0.0) {
    tymin = (min[1] - p[1])*divy;
    tymax = (max[1] - p[1])*divy;
  }
  else{
    tymin = (max[1] - p[1])*divy;
    tymax = (min[1] - p[1])*divy;
  }
  if((tmin > tymax) || (tymin > tmax))
    return false;
  if(tymin > tmin)
    tmin = tymin;
  if(tymax < tmax)
    tmax = tymax;
  float divz = 1/d[2];
  if (divz>=0.0) {
    tzmin = (min[2] - p[2])*divz;
    tzmax = (max[2] - p[2])*divz;
  }
  else{
    tzmin = (max[2] - p[2])*divz;
    tzmax = (min[2] - p[2])*divz;
  }
  if((tmin > tzmax) || (tzmin > tmax))
    return false;
  if(tzmin > tmin)
    tmin = tzmin;
  if(tzmax < tmax)
    tmax = tzmax;
  float t = tmin;
  if(t<0)
    return false;
  if(shadow){
    if(t<=ray->tmax || ray->tmax==-1){
      //printf("shadow t=%f tmax=%f ret=%s\n",t, ray->tmax, t<=ray->tmax?"true":"false");
      return true;
    }
    return false;
  }
  if(t<ray->tmin || ray->tmin==-1.0){
    float * ps = ray->GetP(SHADOW_RAY); 
    ray->CalcPoint(VIEW_RAY,t,ps);
    float tnorm[4]={0.0,0.0,0.0,0.0};
    if(t==txmin){
      //xmax
      if(divx<0)
        tnorm[0]=1.0;
      //xmin
      else
        tnorm[0]=-1.0;
    }
    else if(t==tymin){
      //ymax
      if(divy<0)
        tnorm[1]=1.0;
      //ymin
      else
        tnorm[1]=-1.0;
    }
    else if(t==tzmin){
      //zmax
      if(divz<0)
        tnorm[2]=1.0;
      //zmin
      else
        tnorm[2]=-1.0;
    }
    AFMatXVec(mat_it,tnorm,ray->normal);
    ray->tmin = t;
    SetRayAtt(ray);
    if(image!=NULL){
      float x = p[0] + t*d[0];
      float z = p[2] + t*d[2];
      int s = (int)(x - min[0])*((float)w_image-1.0)/(max[0]-min[0]);
      int t = (int)(z - min[2])*((float)h_image-1.0)/(max[2]-min[2]);
      int img_id = (s*w_image+t)*3;
      float* rcolor = ray->obj_color;
      rcolor[0] = image[img_id+0];
      rcolor[1] = image[img_id+1];
      rcolor[2] = image[img_id+2];
    }
    return true;
  }
}

bool Box::Hit (Ray * ray)
{
  float t_p[4];
  float t_d[4];
  bool shadow = ray->shadow_mode;
  int level = shadow?SHADOW_RAY:VIEW_RAY;
  AFMatXVec(mat_inv,ray->GetP(level),t_p);
  AFMatXVec(mat_inv,ray->GetD(level),t_d);
  //new
  return Hit_aux(ray,t_p,t_d);
}
